package com.jjc.MyWebApp.kit;

import com.jfinal.log.Log;
import com.jjc.MyWebApp.Core.WebAppConfig;

import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.util.Arrays;

/**
 * Pbkdf2加密算法
 * Created by jiaji on 2017/5/10.
 */
public class Pbkdf2Kit {

    private static final Log log = Log.getLog(Pbkdf2Kit.class);

    private static final String PBKDF2_ALGORITHM = "PBKDF2WithHmacSHA1";
    /**
     * 迭代次数
     */
    private static final int PBKDF2_ITERATIONS = 2000;
    /**
     * 生成密文的长度
     */
    private static final int HASH_BIT_SIZE = 128 * 4;
    /**
     * 盐值的长度
     */
    private static final int SALT_BYTE_SIZE = 32 / 2;


    /**
     * 对输入的密码进行验证
     * @param Pwd
     *                      明文
     * @param EncryptedPwd
     *                      密文
     * @param salt
     *                      盐值
     * @return              是否验证成功
     */
    public static boolean authenticate(String Pwd,byte[] EncryptedPwd,byte[] salt){
        byte[] EncryptedAttemptedPwd= getEncryptedPwd(Pwd,salt);
        return Arrays.equals(EncryptedPwd,EncryptedAttemptedPwd);
    }

    /**
     * 生成密文
     *
     * @param Pwd
     *            明文密码
     * @param salt
     *            盐值
     * @return
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeySpecException
     */
    public static byte[] getEncryptedPwd(String Pwd, byte[] salt) {
        byte[] EncryptedPwd = null;
        try {
            KeySpec spec = new PBEKeySpec(Pwd.toCharArray(), salt, PBKDF2_ITERATIONS, HASH_BIT_SIZE);
            SecretKeyFactory f = SecretKeyFactory.getInstance(PBKDF2_ALGORITHM);
            EncryptedPwd = f.generateSecret(spec).getEncoded();
        } catch (Exception e) {
            if (log.isErrorEnabled())log.warn("密文生成失败",e);
            return null;
        }
        return EncryptedPwd;
    }

    /**
     * 生成128位盐值
     * @return 128 bit 盐值
     */
    public static byte[] generateSalt(){
        byte[] salt = new byte[SALT_BYTE_SIZE];
        try {
            SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
            random.nextBytes(salt);
        } catch (NoSuchAlgorithmException e) {
            if (log.isErrorEnabled())log.warn("盐值生成失败",e);
        }
        return salt;
    }
}
